"""
# 消息协议

- 通过各种消息来控制C#的CardEnv
"""
import json


class MsgBase:
    """
    消息基类
    """
    protoName = 'MsgBase'

    def __init__(self, msg_str=None):
        self.load(msg_str)

    def load(self, msg_str):
        cls = type(self)
        attributes = dir(self)
        if not msg_str:
            variables = [a for a in attributes if not (callable(getattr(cls, a)) or (a.startswith('__') and a.endswith('__')))]
            # print(variables)
            values = [getattr(cls, v) for v in variables]
            msg_dc = dict(zip(variables, values))
        else:
            msg_dc = json.loads(msg_str)

        old_proto_name = self.protoName if hasattr(self, 'protoName') else cls.protoName

        # self.__dict__.update(msg_dc)  # 这个会将msg_dc中所有的value都赋值给self
        for key, value in msg_dc.items():
            setattr(self, key, value)

            # if key in attributes:
            #     setattr(self, key, value)
            # else:
            #     print(f"*** MsgBase.load: proto[{old_proto_name}]'s js_string not has key[{key}]!")
        self.protoName = old_proto_name
        return self

    @staticmethod
    def encode(msg_base):
        return json.dumps(msg_base.__dict__)

    def to_string(self):
        return json.dumps(self.__dict__)

    @staticmethod
    def decode(protoName, msg_str, offset=0, count=-1):
        if isinstance(msg_str, MsgBase):
            msg_str = msg_str.to_string()
        elif isinstance(msg_str, dict):
            msg_str = json.dumps(msg_str)

        # if isinstance(msg_str, str):
        #     msg_dc = json.loads(msg_str)
        # elif isinstance(msg_str, dict):
        #     msg_dc = msg_str
        # else:
        #     raise TypeError('msg_str必须为[str, dict, MsgBase]类型!')

        cls = globals().get(protoName)
        msg_obj = cls(msg_str)
        return msg_obj

    def __str__(self):
        return f'{self.protoName}: {self.__dict__}'

    def __repr__(self):
        return f'{self.protoName}: {self.__dict__}'


class MsgAction(MsgBase):
    """
    发送action
    """

    def __init__(self, a=0, i=0):
        self.a = a      # 动作
        self.i = i      # 编号
        self.protoName = 'MsgAction'


class MsgState(MsgBase):
    """
    获取当前State信息
    """
    protoName = 'MsgState'

    state = ""
    info = ""


# region 测试用


class MsgTest(MsgBase):
    """
    MsgTest
    """
    protoName = 'MsgTest'
    info = ""

    def __init__(self, info=""):
        super().__init__()
        self.info = info


class MsgMove(MsgBase):
    """
    移动
    """
    protoName = 'MsgMove'

    x = 0
    y = 0
    z = 0


class MsgAttack(MsgBase):
    """
    移动
    """
    protoName = 'MsgAttack'

    target = '张三'
    desc = '火焰攻击'
# endregion


# region 暂不需要

class MsgReset(MsgBase):
    """
    发送重置消息
    - 获取返回信息
    """
    protoName = 'MsgReset'

    state = ""
    info = ""


class MsgInterval(MsgBase):
    """
    MsgInterval
    """
    protoName = 'MsgInterval'
    interval = 0        # 间隔(毫秒)

    def __init__(self, interval=0):
        super().__init__()

        assert isinstance(interval, int), '请输入操作间隔(毫秒)!'
        self.interval = interval


class MsgInit(MsgBase):
    """
    初始化

    - 与client建立连接
    - 设置变量参数等
    """

    protoName = 'MsgInit'

    total_timesteps = 10000


    pass


class MsgStep(MsgBase):
    """
    发送action并获取返回值
    """
    pass


class MsgGetState(MsgBase):
    pass


class MsgClose(MsgBase):
    protoName = "MsgClose"

# endregion


# region # --- 可能不需要的Msg
# <editor-fold desc="# --- 可能不需要的Msg">
# class ChooseActionMsg(BaseMsg):
#     pass
#
#
# class StepMsg(BaseMsg):
#     pass
#
#
# class RenderMsg(BaseMsg):
#     pass
# </editor-fold>
# endregion



